#pragma once
#include <brpc/server.h>
#include <utility>
#include "base.pb.h"
#include "user.pb.h"
#include "friend.pb.h"
#include "message.pb.h"

#include "etcd.hpp"
#include "channel.hpp"
#include "mysql_relation.hpp"
#include "mysql_chat_session.hpp"
#include "mysql_friend_apply.hpp"
#include "mysql_chat_session_member.hpp"
#include "data_es.hpp"
#include "utils.hpp"
#include "rabbitmq.hpp"
class FriendServiceImpl : public chat_system::FriendService {
public:
    using ptr = std::shared_ptr<FriendServiceImpl>;
    FriendServiceImpl(
        std::shared_ptr<odb::core::database> mysql_client,
        std::shared_ptr<elasticlient::Client> es_client,
        ServiceManager::ptr service_channel,
        const std::string& user_service_name, 
        const std::string& message_service_name)
    : _relation_table(std::make_shared<RelationTable>(mysql_client))
    , _chat_session_table(std::make_shared<ChatSessionTable>(mysql_client))
    , _friend_apply_table(std::make_shared<FriendApplyTable>(mysql_client))
    , _chat_session_member_table(std::make_shared<ChatSessionMemberTable>(mysql_client))
    , _es_client(std::make_shared<ESUser>(es_client))
    , _service_channel(service_channel)
    , _user_service_name(user_service_name)
    , _message_service_name(message_service_name) {}




    virtual void GetFriendList(::google::protobuf::RpcController* controller,
                       const ::chat_system::GetFriendListReq* request,
                       ::chat_system::GetFriendListRsp* response,
                       ::google::protobuf::Closure* done) override {
        // 组织错误响应
        auto err_handle = [&response, &request](const std::string& err_msg)->void {
            response->set_request_id(request->request_id());
            response->set_success(false);
            response->set_errmsg(err_msg);
        };

        brpc::ClosureGuard guard(done);

        std::string user_id = request->user_id();
        if(user_id.empty())
        {
            err_handle("用户ID不能为空");
            LOG_ERROR("用户ID不能为空");
            return;
        }


        // 向mysql发起查询
        auto friend_id_list = _relation_table->friends(user_id);
        if(friend_id_list.empty())
        {
            response->set_request_id(request->request_id());
            response->set_success(true);
            return;
        }


        // 向用户子服务获取用户信息
        std::unordered_set<std::string> friend_ids;
        for(const auto& fid : friend_id_list) {
            friend_ids.emplace(fid);
        }
        std::unordered_map<std::string, chat_system::UserInfo> friend_infos;   

        bool success = _GetUser(request->request_id(), friend_ids, friend_infos);
        if(!success) {
            err_handle("从用户服务获取用户信息失败");
            LOG_ERROR("从用户服务获取用户信息失败");
            return;
        }

        // 组织响应
        for(auto& friend_info : friend_infos) {
            response->mutable_friend_list()->Add(std::move(friend_info.second));
        }
        response->set_request_id(request->request_id());
        response->set_success(true);
        LOG_INFO("GetFriendList 成功: {} 个好友", friend_infos.size());
    }



    virtual void FriendRemove(::google::protobuf::RpcController* controller,
                       const ::chat_system::FriendRemoveReq* request,
                       ::chat_system::FriendRemoveRsp* response,
                       ::google::protobuf::Closure* done) override {
        auto err_handle = [&response, &request](const std::string& err_msg)->void {
            response->set_request_id(request->request_id());
            response->set_success(false);
            response->set_errmsg(err_msg);
        };

        brpc::ClosureGuard guard(done);
        std::string user_id = request->user_id();
        std::string peer_id = request->peer_id();
        if(user_id.empty() || peer_id.empty())
        {
            err_handle("用户ID和好友ID不能为空");
            LOG_ERROR("用户ID和好友ID不能为空");
            return;
        }


        // 向好友关系表发起删除好友请求
        bool success = _relation_table->remove(user_id, peer_id);
        if(!success)
        {
            LOG_ERROR("删除好友失败, {}", user_id + "-" + peer_id);
            err_handle("删除好友失败");
            return;
        }

        // 向会话表发起删除会话请求
        success = _chat_session_table->remove(user_id, peer_id);
        if(!success)
        {
            LOG_ERROR("删除会话失败, {}", user_id + "-" + peer_id);
            err_handle("删除会话失败");
            return;
        }


        // 组织响应
        response->set_request_id(request->request_id());
        response->set_success(true);
        LOG_INFO("删除好友成功: {} - {}", user_id, peer_id);
    }



    virtual void FriendAdd(::google::protobuf::RpcController* controller,
                       const ::chat_system::FriendAddReq* request,
                       ::chat_system::FriendAddRsp* response,
                       ::google::protobuf::Closure* done) override {
        auto err_handle = [&response, &request](const std::string& err_msg)->void {
            response->set_request_id(request->request_id());
            response->set_success(false);
            response->set_errmsg(err_msg);
        };
        brpc::ClosureGuard guard(done);
        

        std::string user_id = request->user_id();
        std::string respondent_id = request->respondent_id();

        // 是否已经是好友
        if(_relation_table->exists(user_id, respondent_id)) {
            err_handle("已经是好友关系");
            LOG_ERROR("已经是好友关系: {} - {}", user_id, respondent_id);
            return;
        }
        // 是否已经发送过好友请求
        if(_friend_apply_table->exists(user_id, respondent_id)) {
            err_handle("已经发送过好友请求");
            LOG_ERROR("已经发送过好友请求: {} - {}", user_id, respondent_id);
            return;
        }
        // 向好友申请表插入好友申请
        std::string event_id = uuid();
        bool success = _friend_apply_table->insert(FriendApply(event_id, user_id, respondent_id));
        if(!success) {
            err_handle("插入好友申请失败");
            LOG_ERROR("插入好友申请失败: {} - {}", user_id, respondent_id);
            return;
        }

        // 填充响应
        response->set_request_id(request->request_id());
        response->set_success(true);
        response->set_notify_event_id(event_id);
    }
    
    
    
    virtual void FriendAddProcess(::google::protobuf::RpcController* controller,
                       const ::chat_system::FriendAddProcessReq* request,
                       ::chat_system::FriendAddProcessRsp* response,
                       ::google::protobuf::Closure* done) override {
        auto err_handle = [&response, &request](const std::string& err_msg)->void {
            response->set_request_id(request->request_id());
            response->set_success(false);
            response->set_errmsg(err_msg);
        };
        brpc::ClosureGuard guard(done);

        std::string event_id = request->notify_event_id();
        bool agree = request->agree();
        std::string apply_user_id = request->apply_user_id();
        std::string user_id = request->user_id();

        // 从好友申请表删除好友申请
        if(!_friend_apply_table->exists(apply_user_id, user_id)) {
            err_handle("好友申请不存在");
            LOG_ERROR("好友申请不存在: {} - {} - {}", event_id, apply_user_id, user_id);
            return;
        }

        bool success = _friend_apply_table->remove(apply_user_id, user_id);
        if(!success) {
            err_handle("删除好友申请失败");
            LOG_ERROR("删除好友申请失败: {} - {} - {}", event_id, apply_user_id, user_id);
            return;
        }

        // 同意则插入好友关系
        std::string new_session_id;
        if(agree) {
            new_session_id = uuid();
            success = _relation_table->insert(user_id, apply_user_id);
            if(!success) {
                err_handle("插入好友关系失败");
                LOG_ERROR("插入好友关系失败: {} - {} - {}", event_id, apply_user_id, user_id);
                return;
            }
            success = _chat_session_table->insert(ChatSession(new_session_id, "", ChatSessionType::SINGLE));
            if(!success) {
                err_handle("插入会话失败");
                LOG_ERROR("插入会话失败: {} - {} - {}", event_id, apply_user_id, user_id);
                return;
            }

            ChatSessionMember csm1(new_session_id, user_id);
            ChatSessionMember csm2(new_session_id, apply_user_id);
            success = _chat_session_member_table->append({csm1, csm2});

            if(!success) {
                err_handle("插入会话成员失败");
                LOG_ERROR("插入会话成员失败: {} - {} - {}", event_id, apply_user_id, user_id);
                return;
            }
        }


        // 填充响应    
        response->set_request_id(request->request_id());
        response->set_success(true);
        response->set_new_session_id(new_session_id);
        LOG_INFO("处理好友申请成功: {} - {} - {} - {}", event_id, apply_user_id, user_id, agree);
    }



    virtual void FriendSearch(::google::protobuf::RpcController* controller,
                       const ::chat_system::FriendSearchReq* request,
                       ::chat_system::FriendSearchRsp* response,
                       ::google::protobuf::Closure* done) override {
        auto err_handle = [&response, &request](const std::string& err_msg)->void { 
            response->set_request_id(request->request_id());
            response->set_success(false);
            response->set_errmsg(err_msg);
        };
        brpc::ClosureGuard guard(done);

        
        std::string search_key = request->search_key();
        std::string user_id = request->user_id();
        if(user_id.empty()) {
            err_handle("用户ID不能为空");
            LOG_ERROR("用户ID不能为空");
            return;
        }


        // 向es发起查询
        std::vector<std::string> exclude_user_id_list = _relation_table->friends(user_id);
        exclude_user_id_list.emplace_back(user_id);
        std::vector<User> search_res = _es_client->search(search_key, exclude_user_id_list);
        
        if(search_res.empty()) {
            response->set_request_id(request->request_id());
            response->set_success(true);
            return;
        }

        // 向用户子服务获取用户信息
        std::unordered_set<std::string> user_ids;
        for(const auto& user : search_res) {
            user_ids.emplace(user.user_id());
        }
        std::unordered_map<std::string, chat_system::UserInfo> user_infos;
        bool success = _GetUser(request->request_id(), user_ids, user_infos);
        if(!success) {
            err_handle("从用户服务获取用户信息失败");
            LOG_ERROR("从用户服务获取用户信息失败");
            return;
        }


        // 组织响应
        for(auto& user_info : user_infos) {
            response->mutable_user_info()->Add(std::move(user_info.second));
        }   
        response->set_request_id(request->request_id());
        response->set_success(true);
        LOG_INFO("FriendSearch 成功: {} 个用户", user_infos.size());
    }



    virtual void GetChatSessionList(::google::protobuf::RpcController* controller,
                       const ::chat_system::GetChatSessionListReq* request,
                       ::chat_system::GetChatSessionListRsp* response,
                       ::google::protobuf::Closure* done) override {
        auto err_handle = [&response, &request](const std::string& err_msg)->void {
            response->set_request_id(request->request_id());
            response->set_success(false);
            response->set_errmsg(err_msg);
        };
        brpc::ClosureGuard guard(done);

        std::string user_id = request->user_id();
        if(user_id.empty())
        {
            err_handle("用户ID不能为空");
            LOG_ERROR("用户ID不能为空");
            return;
        }

        // 向_chat_session_table发起查询
        auto single_session_list = _chat_session_table->singleChatSession(user_id);


        // 获取单聊会话的好友信息
        std::unordered_set<std::string> friend_ids;
        for(const auto& session : single_session_list) {
            friend_ids.emplace(session._friend_id);
        }
        std::unordered_map<std::string, chat_system::UserInfo> friend_infos;
        bool success = _GetUser(request->request_id(), friend_ids, friend_infos);
        if(!success) {
            err_handle("从用户服务获取用户信息失败");
            LOG_ERROR("从用户服务获取用户信息失败");
            return;
        }


        // 获取群聊会话的信息
        auto group_session_list = _chat_session_table->groupChatSession(user_id);


        // 组织响应
        for (const auto& session : single_session_list) {
            chat_system::ChatSessionInfo* chat_session_info = response->add_chat_session_info_list();
            chat_system::MessageInfo msg;
            chat_session_info->set_single_chat_friend_id(session._friend_id);
            chat_session_info->set_chat_session_id(session._chat_session_id);
            chat_session_info->set_chat_session_name(friend_infos[session._friend_id].nickname());
            chat_session_info->set_avatar(friend_infos[session._friend_id].avatar());

            bool success = _GetRecentMsg(request->request_id(), session._chat_session_id, msg);
            if(!success) {
                LOG_DEBUG("获取最近消息失败: {}", session._chat_session_id);
                continue;
            }
            chat_session_info->mutable_prev_message()->CopyFrom(msg);
        }   

        for (const auto& session : group_session_list) {
            chat_system::ChatSessionInfo* chat_session_info = response->add_chat_session_info_list();
            chat_system::MessageInfo msg;
            chat_session_info->set_chat_session_id(session._chat_session_id);
            chat_session_info->set_chat_session_name(session._chat_session_name);

            bool success = _GetRecentMsg(request->request_id(), session._chat_session_id, msg);
            if(!success) {
                LOG_DEBUG("获取最近消息失败: {}", session._chat_session_id);
                continue;
            }
            chat_session_info->mutable_prev_message()->CopyFrom(msg);
        }

        response->set_request_id(request->request_id());
        response->set_success(true);
        LOG_INFO("GetChatSessionList 成功: {} 个会话", response->chat_session_info_list_size());
    }


    // 创建群聊会话
    virtual void ChatSessionCreate(::google::protobuf::RpcController* controller,
                       const ::chat_system::ChatSessionCreateReq* request,
                       ::chat_system::ChatSessionCreateRsp* response,
                       ::google::protobuf::Closure* done) override {
        auto err_handle = [&response, &request](const std::string& err_msg)->void {
            response->set_request_id(request->request_id());
            response->set_success(false);
            response->set_errmsg(err_msg);
        };
        brpc::ClosureGuard guard(done);


        std::string user_id = request->user_id();
        if(user_id.empty())
        {
            err_handle("用户ID不能为空");
            LOG_ERROR("用户ID不能为空");
            return;
        }
        std::string chat_session_name = request->chat_session_name();
        if(chat_session_name.empty())
        {
            err_handle("会话名称不能为空");
            LOG_ERROR("会话名称不能为空");
            return;
        }
        auto& member_id_list = request->member_id_list();
        if (member_id_list.size() < 3) {
            err_handle("群聊成员不能少于3人");
            LOG_ERROR("群聊成员不能少于3人");
            return;
        }


        // 向会话表插入会话
        std::string chat_session_id = uuid();
        bool success = _chat_session_table->insert(ChatSession(chat_session_id, chat_session_name, ChatSessionType::GROUP));
        if(!success) {
            err_handle("插入会话失败");
            LOG_ERROR("插入会话失败: {}", chat_session_id);
            return;
        }


        // 向会话成员表插入会话成员
        for(auto& member_id : member_id_list) {
            if(member_id.empty()) {
                err_handle("会话成员ID不能为空");
                LOG_ERROR("会话成员ID不能为空");
                return;
            }
            _chat_session_member_table->append(ChatSessionMember(chat_session_id, member_id));
        }


        // 组织响应
        response->set_request_id(request->request_id());
        response->set_success(true);
        response->mutable_chat_session_info()->set_chat_session_id(chat_session_id);
        response->mutable_chat_session_info()->set_chat_session_name(chat_session_name);
        LOG_INFO("创建群聊会话成功: {} - {}", chat_session_id, chat_session_name);
    }


    // 获取群聊成员信息
    virtual void GetChatSessionMember(::google::protobuf::RpcController* controller,
                       const ::chat_system::GetChatSessionMemberReq* request,
                       ::chat_system::GetChatSessionMemberRsp* response,
                       ::google::protobuf::Closure* done) override {
        auto err_handle = [&response, &request](const std::string& err_msg)->void {
            response->set_request_id(request->request_id());
            response->set_success(false);
            response->set_errmsg(err_msg);
        };
        brpc::ClosureGuard guard(done);


        std::string chat_session_id = request->chat_session_id();
        if(chat_session_id.empty())
        {
            err_handle("会话ID不能为空");
            LOG_ERROR("会话ID不能为空");
            return;
        }
        std::string user_id = request->user_id();
        if(user_id.empty())
        {
            err_handle("用户ID不能为空");
            LOG_ERROR("用户ID不能为空");
            return;
        }


        auto member_id_list = _chat_session_member_table->members(chat_session_id);
        std::unordered_set<std::string> member_ids;
        for(auto id : member_id_list) {
            if(id.empty()) {
                err_handle("会话成员ID不能为空");
                LOG_ERROR("会话成员ID不能为空");
                return;
            }
            member_ids.emplace(id);
        }
        // 向用户子服务获取用户信息
        std::unordered_map<std::string, chat_system::UserInfo> member_infos;
        bool success = _GetUser(request->request_id(), member_ids, member_infos);
        if(!success) {
            err_handle("从用户服务获取用户信息失败");
            LOG_ERROR("从用户服务获取用户信息失败");
            return;
        }
        // 组织响应
        for(const auto& member_id : member_id_list) {
            auto member_info_list = response->add_member_info_list();
            member_info_list->CopyFrom(member_infos[member_id]);
        }
        response->set_request_id(request->request_id());
        response->set_success(true);
        LOG_INFO("GetChatSessionMember 成功: {} 个成员", response->member_info_list_size());
    }

    
    
    virtual void GetPendingFriendEventList(::google::protobuf::RpcController* controller,
                       const ::chat_system::GetPendingFriendEventListReq* request,
                       ::chat_system::GetPendingFriendEventListRsp* response,
                       ::google::protobuf::Closure* done) override {
        auto err_handle = [&response, &request](const std::string& err_msg)->void {
            response->set_request_id(request->request_id());
            response->set_success(false);
            response->set_errmsg(err_msg);
        };
        brpc::ClosureGuard guard(done);

        std::string user_id = request->user_id();
        if(user_id.empty())
        {
            err_handle("用户ID不能为空");
            LOG_ERROR("用户ID不能为空");
            return;
        }


        // 向好友申请表发起查询
        auto apply_id_list = _friend_apply_table->applyUsers(user_id);
        if(apply_id_list.empty()) {
            response->set_request_id(request->request_id());
            response->set_success(true);
            return;
        }

        // 向用户子服务获取用户信息
        std::unordered_set<std::string> apply_ids;
        for(const auto& aid : apply_id_list) {
            apply_ids.emplace(aid);
        }
        std::unordered_map<std::string, chat_system::UserInfo> apply_infos;
        bool success = _GetUser(request->request_id(), apply_ids, apply_infos);
        if(!success) {
            err_handle("从用户服务获取用户信息失败");
            LOG_ERROR("从用户服务获取用户信息失败");
            return;
        }

        
        // 组织响应
        for(auto& apply_info : apply_infos) {
            auto event = response->add_event();
            event->mutable_sender()->CopyFrom(apply_info.second);
        }
        response->set_request_id(request->request_id());
        response->set_success(true);
        LOG_INFO("GetPendingFriendEventList 成功: {} 个事件", response->event_size());
    }

private:
    bool _GetRecentMsg(const std::string &request_id,
                       const std::string &chat_session_id,
                       chat_system::MessageInfo &msg) {

        auto channel_manager = _service_channel->choose(_message_service_name);
        if(channel_manager == nullptr) {
            LOG_DEBUG("获取消息存储服务信道失败");
            return false;
        }
        // 获取消息存储服务信道
        auto channel = channel_manager->choose();
        if(channel == nullptr) {
            LOG_DEBUG("获取消息存储服务信道失败");
            return false;
        }

        chat_system::GetRecentMsgReq req;
        chat_system::GetRecentMsgRsp rsp;
        req.set_chat_session_id(chat_session_id);
        req.set_msg_count(1);
        brpc::Controller cntl;
        chat_system::MsgStorageService_Stub stub(channel.get());
        stub.GetRecentMsg(&cntl, &req, &rsp, nullptr);
        if(cntl.Failed() || !rsp.success()) {
            LOG_ERROR("获取最近消息失败: {} - {}", rsp.errmsg(), cntl.ErrorText());
            return false;
        }

        if(rsp.msg_list_size() == 0) {
            LOG_DEBUG("会话{}没有消息", chat_session_id);
            return false;
        }
        msg.CopyFrom(rsp.msg_list(0));
        LOG_DEBUG("获取最近消息成功: {}", msg.DebugString());
        return true;
    }


    bool _GetUser(const std::string &req_id,
                  const std::unordered_set<std::string> &user_ids,
                  std::unordered_map<std::string, chat_system::UserInfo> &user_info) {
        //获取用户服务信道管理对象
        auto channel_manager = _service_channel->choose(_user_service_name);
        if(channel_manager == nullptr) {
            LOG_ERROR("获取用户服务信道失败");
            return false;
        }
        // 获取用户服务信道
        auto channel = channel_manager->choose();
        if(channel == nullptr) {
            LOG_ERROR("获取用户服务信道失败");
            return false;
        }
        
        
        // 向用户管理子服务发起RPC调用, 获取用户信息
        chat_system::UserService_Stub stub(channel.get());
        chat_system::GetMultiUserInfoReq req;
        chat_system::GetMultiUserInfoRsp rsp;
        req.set_request_id(req_id);
        for(const auto& user_id : user_ids) {
            if(user_id.empty()) continue;
            req.add_users_id(user_id);
        }

        brpc::Controller cntl;  
        stub.GetMultiUserInfo(&cntl, &req, &rsp, nullptr);
        LOG_DEBUG("---{}---{}---", cntl.Failed(), rsp.success());
        if(cntl.Failed() || !rsp.success()) {
            LOG_ERROR("获取用户信息失败: {}---{}---", rsp.errmsg(), cntl.ErrorText());
            return false;
        }

        // 获取用户信息成功
        for(const auto& user : rsp.users_info()) {
            user_info.insert(std::make_pair(user.first, user.second));
        }
        return true;
    }   



private:
    RelationTable::ptr _relation_table;
    FriendApplyTable::ptr _friend_apply_table;
    ChatSessionTable::ptr _chat_session_table;
    ChatSessionMemberTable::ptr _chat_session_member_table;
    ESUser::ptr _es_client;
    ServiceManager::ptr _service_channel;
    std::string _user_service_name;
    std::string _message_service_name;
};



class FriendServer {
public:
    using ptr = std::shared_ptr<FriendServer>;

    FriendServer (Registry::ptr registry_client,
                Discovery::ptr discovery_client,
                std::shared_ptr<odb::core::database> mysql_client,
                std::shared_ptr<elasticlient::Client> es_client,
                std::shared_ptr<brpc::Server> server)
    : _registry_client(registry_client)
    , _discovery_client(discovery_client)
    , _mysql_client(mysql_client)
    , _es_client(es_client)
    , _server(server) {}


    void start() {
        LOG_INFO("用户管理服务已启动");
        _server->RunUntilAskedToQuit();
    }

private:
    
    Registry::ptr _registry_client;
    Discovery::ptr _discovery_client;

    std::shared_ptr<odb::core::database> _mysql_client;
    std::shared_ptr<elasticlient::Client> _es_client;

    std::shared_ptr<brpc::Server> _server;
};



class FriendServerBuilder { 
public:
    void make_reg_object(const std::string &etcd_host, const std::string& service_name, const std::string service_host) {
        _registry_client = std::make_shared<Registry>(etcd_host);
        bool success = _registry_client->registry(service_name, service_host);
        if(!success)
        {
            LOG_ERROR("注册服务到etcd失败");
            return;
        }
        LOG_INFO("注册服务{} - {}到etcd成功", service_name, service_host);
    }


    void make_rpc_object(uint16_t port, int32_t timeout, uint8_t num_threads) {
        logging::LoggingSettings tmp_log;
        tmp_log.logging_dest = logging::LOG_TO_NONE;
        logging::InitLogging(tmp_log);
        _server = std::make_shared<brpc::Server>();
        int ret = _server->AddService(_friend_service_impl.get(), brpc::SERVER_DOESNT_OWN_SERVICE);
        if(ret < 0)
        {
            LOG_ERROR("注册服务失败");
            return;
        }
        brpc::ServerOptions options;
        options.idle_timeout_sec = timeout;
        options.num_threads = num_threads;
        ret = _server->Start(port, &options);
        if(ret < 0)
        {
            LOG_ERROR("启动服务器失败");
            abort();  
        }
    }


    void make_discovery_object(const std::string &etcd_host, const std::string &basedir, const std::string &user_service_name, const std::string &message_service_name) {
        _user_service_name = basedir + user_service_name;
        _message_service_name = basedir + message_service_name;
        _service_manager = std::make_shared<ServiceManager>();     
        _service_manager->declared(_user_service_name);   
        _service_manager->declared(_message_service_name);
        auto put_cb = std::bind(&ServiceManager::onServiceOnline, _service_manager, std::placeholders::_1, std::placeholders::_2);
        auto del_cb = std::bind(&ServiceManager::onServiceOffline, _service_manager, std::placeholders::_1, std::placeholders::_2);
        _discovery_client = std::make_shared<Discovery>(etcd_host, basedir, put_cb, del_cb);
        if(_discovery_client == nullptr)
        {
            LOG_ERROR("创建服务发现对象失败");
            abort();
        }
        
    }


    void make_mysql_object(
        const std::string &user,
        const std::string &pswd,
        const std::string &host,
        const std::string &db,
        const std::string &cset,
        int port,
        int conn_pool_count) {
        _mysql_client = ODBFactory::create(user, pswd, db, host, port, cset, conn_pool_count);
    }


    void make_es_object(const std::vector<std::string>& es_addr_list) {
        _es_client = ESClientFactory::create(es_addr_list); 
    }

    void make_friend_service_impl() {
        _friend_service_impl = std::make_shared<FriendServiceImpl>(_mysql_client, _es_client, _service_manager, _user_service_name, _message_service_name);
    }
    FriendServer::ptr build() {
        if(_friend_service_impl == nullptr)
        {
            LOG_ERROR("用户服务实例未创建");
            return nullptr;
        }
        if(_registry_client == nullptr)
        {
            LOG_ERROR("注册中心对象未创建");
            return nullptr;
        }
        if(_server == nullptr)
        {
            LOG_ERROR("RPC服务器对象未创建");
            return nullptr;
        }


        if(_discovery_client == nullptr)
        {
            LOG_ERROR("服务发现对象未创建");
            return nullptr;
        }

        return std::make_shared<FriendServer>(_registry_client, _discovery_client, _mysql_client, _es_client, _server);
    }
private:
    std::string _user_service_name;
    std::string _message_service_name;

    FriendServiceImpl::ptr _friend_service_impl;
    
    Registry::ptr _registry_client;
    Discovery::ptr _discovery_client;
    ServiceManager::ptr _service_manager;

    std::shared_ptr<odb::core::database> _mysql_client;
    std::shared_ptr<elasticlient::Client> _es_client;

    std::shared_ptr<brpc::Server> _server;
};    
